#include "Matrix3x3.h"

namespace lib3dw
{
	Matrix3x3 operator + (const Matrix3x3 &m, const Matrix3x3 &n)
	{
		return Matrix3x3(m.rows[0] + n.rows[0], m.rows[1] + n.rows[1], m.rows[2] + n.rows[2]);
	}

	Matrix3x3 operator - (const Matrix3x3 &m, const Matrix3x3 &n)
	{
		return Matrix3x3(m.rows[0] - n.rows[0], m.rows[1] - n.rows[1], m.rows[2] - n.rows[2]);
	}

	Matrix3x3 operator - (const Matrix3x3 &m)
	{
		return Matrix3x3(-m.rows[0], -m.rows[1], -m.rows[2]);
	}

#define rcDot3(r, c) (m.rows[r].x * n.rows[0][c] + m.rows[r].y * n.rows[1][c] + m.rows[r].z * n.rows[2][c])

	Matrix3x3 operator * (const Matrix3x3 &m, const Matrix3x3 &n)
	{
		return Matrix3x3(
			rcDot3(0, 0), rcDot3(0, 1), rcDot3(0, 2),
			rcDot3(1, 0), rcDot3(1, 1), rcDot3(1, 2),
			rcDot3(2, 0), rcDot3(2, 1), rcDot3(2, 2));
	}

	Vector3 operator * (const Matrix3x3 &m, const Vector3 &v)
	{
		return Vector3(dot(m.rows[0], v), dot(m.rows[1], v), dot(m.rows[2], v));
	}

	Matrix3x3 operator * (const Matrix3x3 &m, const float x)
	{
		return Matrix3x3(m.rows[0] * x, m.rows[1] * x, m.rows[2] * x);
	}

	Matrix3x3 transpose(const Matrix3x3 &m)
	{
		return Matrix3x3(
			m.rows[0].x, m.rows[1].x, m.rows[2].x,
			m.rows[0].y, m.rows[1].y, m.rows[2].y,
			m.rows[0].z, m.rows[1].z, m.rows[2].z);
	}

	float det(const Matrix3x3 &m)
	{
		return 
			m.rows[0].x * (m.rows[1].y * m.rows[2].z - m.rows[2].y * m.rows[1].z) -
			m.rows[0].y * (m.rows[1].x * m.rows[2].z - m.rows[1].z * m.rows[2].x) +
			m.rows[0].z * (m.rows[1].x * m.rows[2].y - m.rows[1].y * m.rows[2].x);
	}
}